import os
import pathlib

from pyfakefs.fake_filesystem_unittest import Patcher

from library_test.mock_manage.mock_model.testcase_model import FileConfigGroup


class MockTarInfo:

    def __init__(self, name, size=0, mode=0o644, mtime=0, uid=0, gid=0, uname="root", gname="root"):
        self.name = name
        self.size = size
        self.mode = mode
        self.mtime = mtime
        self.uid = int(uid)
        self.gid = int(gid)
        self.uname = uname
        self.gname = gname


class MockFileHandler:

    def __init__(self):
        self.patcher = Patcher()

    def start_mock(self):
        self.patcher.setUp()

    def add_file(self, file_config: FileConfigGroup):
        for mock_dir in file_config.dirs:
            self.patcher.fs.create_dir(mock_dir)
        for mock_file in file_config.files:
            self.patcher.fs.create_file(mock_file.path, contents=mock_file.template)
        for mock_file in file_config.compress_files:
            self.patcher.fs.create_file(mock_file.path)

    def end_mock(self):
        self.patcher.tearDown()


class MockCompressContext:

    def __init__(self, mock_file_handler: MockFileHandler, file_path, members: FileConfigGroup):
        self.mock_file_handler = mock_file_handler
        self.file_path = file_path
        self.file_name = os.path.basename(file_path).replace(".tar", "").replace(".gz", "")
        self.members = members

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    def extractall(self, extra_dir):
        extra_path = os.path.join(extra_dir, self.file_name)
        self.mock_file_handler.patcher.fs.create_dir(extra_path)
        for new_dir in self.members.dirs:
            os.makedirs(os.path.join(extra_path, new_dir))
        for new_file in self.members.files:
            open(os.path.join(extra_path, new_file.path, ), "w").write(new_file.template)
        for new_file in self.members.compress_files:
            open(os.path.join(extra_path, new_file.path, ), "w").write("")

    def getmembers(self):
        members = []
        members.extend([MockTarInfo(os.path.join(self.file_name, file.path)) for file in self.members.files])
        members.extend([MockTarInfo(os.path.join(self.file_name, file.path)) for file in self.members.compress_files])
        members.extend([MockTarInfo(os.path.join(self.file_name, new_dir)) for new_dir in self.members.dirs])
        return members


class MockCompressFileHandler:

    def __init__(self, mock_file_handler: MockFileHandler, file_config: FileConfigGroup):
        self.mock_file_handler = mock_file_handler
        self.members_dict = {compress_file.path: compress_file.members for compress_file in file_config.compress_files}

    def open(self, file_path, mode="r", *args, **kwargs):
        path = pathlib.Path(file_path).as_posix()
        return MockCompressContext(self.mock_file_handler, path, self.members_dict.get(path))
